package psd;

import java.io.*;
import java.util.*;
import java.text.*;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;

public class MatchMaker {

	static public void main(String[] args) {

		MatchMaker parser = new MatchMaker();
		parser.parse(args);

	}

	ArrayList<RegRecord> folks = new ArrayList<RegRecord>();



	// Database connection
	Connection connection = null;



	private String database;


	Map<Integer, RegRecord> loadRecords(Connection connection)
			throws SQLException {

		Statement statement = connection.createStatement();
		statement.setQueryTimeout(30); // set timeout to 30 sec.

		System.out.println("Loading reg records");
		ResultSet rs = statement.executeQuery("select "
				+ "regrecord.id, nickname, regrecord.location, regrecord.friend_dates, "
				+ "email, add_to_mailings, seek_groups, groups_match_all, paid, pending, stationary, comments, referred_by, notes, psdid"
				+ " from register_regrecord as regrecord "
				+ " where regrecord.event = 'macaw1';");

		Map<Integer, RegRecord> rrs = new HashMap<Integer, RegRecord>();
		while (rs.next()) {
			// read the result set
			RegRecord record = new RegRecord(false);

			record.setLocations(rs.getString("location"));

			// !!!!!
			// TODO: Do seeking group stuff
			record.setLookGroup( rs.getBoolean("seek_groups"), !rs.getBoolean("groups_match_all"));
			
			record.setPubname( rs.getString("nickname") );
			record.email = rs.getString("email");
			record.add_to_list = rs.getBoolean("add_to_mailings");
			record.setFriendship(rs.getBoolean("friend_dates"));

			record.setPaid(rs.getBoolean("paid"));
			record.setPending(rs.getBoolean("pending"));
			record.setNotes( rs.getString( "notes"));
			record.setReferred(rs.getString("referred_by"));
			record.setComments(rs.getString("comments"));
			record.setID(rs.getString("psdid"));
			record.setTimeStamp( rs.getInt("id"));
			record.setStationary( rs.getBoolean("stationary"));
			// System.out.println("regrecord psdid = " +
			// rs.getString("regrecord.psdid"));

			rrs.put(rs.getInt("id"), record);
			
			System.out.print(" r" + rs.getInt("id"));
		}
		System.out.println( "\n" );
		return rrs;
	}

	void saveGeekCodes( Connection con ) throws SQLException {
		System.err.println( "Updating geek codes in database\n");
		for ( RegRecord f : folks ) {
			Statement statement = con.createStatement();
			statement.setQueryTimeout(30); // set timeout to 30 sec.
			statement.executeUpdate("UPDATE register_regrecord SET geek_code='"
					+ f.geekCode() + "' WHERE psdid='" + f.id() + "';" );
			
		}
	}
	
	Map<Integer, Person> loadPeople(Connection connection) throws SQLException {

		System.out.println("Loading person records");
		Statement statement = connection.createStatement();
		statement.setQueryTimeout(30); // set timeout to 30 sec.

		Map<Integer, Person> peeps = new HashMap<Integer, Person>();
		ResultSet rs = statement
				.executeQuery("select "
						+ "person.id, "
						+ "person.first_name, person.last_name, person.gender, person.age, person.seeking_primary, "
						+ "person.kinky, person.seek_gender, person.seek_age_min, person.seek_age_max, "
						+ "person.seek_kinkiness, person.psdid "
						+ "from register_person as person, register_regrecord as regrecord, register_regrecord_people "
						+ "as joiner where  person.id = joiner.person_id and regrecord.id = joiner.regrecord_id;");

		while (rs.next()) {
			// read the result set
			Person record = new Person();

			record.setAge(rs.getInt("age"));
			record.setAgeRange(rs.getInt("seek_age_min"), rs
					.getInt("seek_age_max"));

			record.setLookGenders(rs.getString("seek_gender"));
			record.setGenders(rs.getString("gender"));

			record.setName( rs.getString("first_name"), rs.getString("last_name") );
			
			record.setKinky(rs.getBoolean("kinky"));
			record.setLookKinky(rs.getString("seek_kinkiness"));

			// no primary is the "same as" seeking primary: i.e.,
			// those who have no primary are often seeking one.
			record.setPrimary(rs.getBoolean("seeking_primary"));

			peeps.put(rs.getInt("id"), record);
			System.out.print(" p" + rs.getInt("id"));
		}
		System.out.println('\n');
		return peeps;
	}

	public void parse(String[] args) {

		if (args == null || args.length == 0) {
			printUsage();
			return;
		}
		
		database = args[args.length-1];

		// Setup registration
		try {
			Class.forName("org.sqlite.JDBC");
		} catch (Exception e) {
			System.err.println("Could not load sqlite driver");
			return;
		}

		try {
			connection = DriverManager.getConnection("jdbc:sqlite:" + database );
			
			Map<Integer, RegRecord> regRecs = loadRecords(connection);
			Map<Integer, Person> peeps = loadPeople(connection);

			mergeRecords(connection, regRecs, peeps);
			
			saveGeekCodes(connection);
			
			connection.close();

		} catch (SQLException e) {
			System.err.println("error reading from database:");
			System.err.println(e.getMessage());
			return;
		}

		
		// now do matching and write everything out.
		Matcher m = new Matcher( args );
		m.match( folks );

	}

	private void mergeRecords(Connection connection,
			Map<Integer, RegRecord> regRecs, Map<Integer, Person> peeps)
			throws SQLException {

		System.out.println("Merging records");
		Statement statement = connection.createStatement();
		statement.setQueryTimeout(30); // set timeout to 30 sec.
		ResultSet rs = statement.executeQuery("select "
				+ "person_id as pid, regrecord_id as rid "
				+ "from register_regrecord_people " + "as joiner;");

		while (rs.next()) {
			// read the result set
			RegRecord r = regRecs.get(rs.getInt("rid"));
			if (r != null) {
				Person p = peeps.get(rs.getInt("pid"));
				if (p != null) {
					r.addPeep(p);
				} else {
					System.err.println("MISSING PERSON for regreg " + r
							+ "\n\t" + rs.getInt("rid") + " to "
							+ rs.getInt("pid"));
				}
			}
		}
		Collection<RegRecord> entrySet = (Collection<RegRecord>) regRecs
				.values();
		folks.addAll(entrySet);
		for (RegRecord f : folks) {
			f.cleanUp();
		}
	}

	

	private void printUsage() {
		System.err
				.println("usage: java MatchMaker [-output <output file>] [-no_comments] [-file_name_ids]"
						+ "[-matrix <output file>] database_file");
	}

	
}
